using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections.ObjectModel;
using MyPhotoIndex.Interfaces.FileSearch;

namespace MyPhotoIndex.Utilities
{
    public class FilesSearch
    {
        public event EventHandler<FileSearchEventAgs>   FilesSearchEvent;

        private bool                                    m_searchSubfolders;
        private string                                  m_searchPattern;
        private bool                                    m_ignoreSystemFolders;
        private List<string>                            m_searchLocations;
        private List<string>                            m_fileList;
        private bool                                    m_stopSearch;
        private ReadOnlyCollection<IFileSearchFilter>   m_filters;

        public FilesSearch()
        {
            m_searchLocations = new List<string>();
            m_fileList = new List<string>();
        }

        public void Search()
        {
            m_stopSearch = false;
            foreach (string dir in m_searchLocations)
            {
                if (Ignore(dir) == false)
                {
                    SearchInternal(dir);
                }

                if (m_stopSearch == true)
                {
                    break;
                }
            }
        }

        private bool Ignore(string dir)
        {
            return false;
        }

        public void Stop()
        {
            m_stopSearch = true;
        }

        internal void SearchInternal(string dir)
        {
            try
            {
                string[] searchPatterns = m_searchPattern.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string searchPattern in searchPatterns)
                {
                    if (string.IsNullOrEmpty(searchPattern))
                    {
                        continue;
                    }

                    try
                    {
                        string[] fileList = Directory.GetFiles(dir, searchPattern, SearchOption.TopDirectoryOnly);
                        foreach (string file in fileList)
                        {
                            if (m_fileList.Contains(file) == false &&
                                CheckFilters(file) == true)
                            {
                                m_fileList.Add(file);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Log(ex);
                    }

                    if (FilesSearchEvent != null)
                    {
                        FilesSearchEvent.Invoke(this, new FileSearchEventAgs(dir, m_fileList.Count));
                    }
                }
            }
            catch (Exception ex)
            {
                string msg = ex.Message;
            }

            if (m_searchSubfolders == true)
            {
                try
                {
                    string[] dirList = Directory.GetDirectories(dir);
                    foreach (string subDir in dirList)
                    {
                        if (Ignore(subDir) == false)
                        {
                            SearchInternal(subDir);
                        }

                        if (m_stopSearch == true)
                        {
                            break;
                        }
                    }
                }
                catch (Exception ex)
                {
                    string msg = ex.Message;
                }
            }
        }

        private bool CheckFilters(string file)
        {
            if (m_filters == null ||
                m_filters.Count == 0)
            {
                return true;
            }

            FileInfo fi = new FileInfo(file);
            foreach (IFileSearchFilter filter in m_filters)
            {
                if (filter.Check(fi) == false)
                {
                    return false;
                }
            }

            return true;
        }

        public string SearchPattern
        {
            get { return m_searchPattern; }
            set { m_searchPattern = value; }
        }

        public bool SearchSubfolders
        {
            get { return m_searchSubfolders; }
            set { m_searchSubfolders = value; }
        }

        public bool IgnoreSystemFolders
        {
            get { return m_ignoreSystemFolders; }
            set { m_ignoreSystemFolders = value; }
        }

        public List<string> SearchLocations
        {
            get { return m_searchLocations; }
        }

        public ReadOnlyCollection<string> FileList
        {
            get { return m_fileList.AsReadOnly(); }
        }

        public ReadOnlyCollection<IFileSearchFilter> Filter
        {
            get { return m_filters; }
            set { m_filters = value; }
        }
    }
}
